<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Common\IdxCtl;

use Srv\Libs\Common\CommString;
use Srv\Libs\Common\CommValid;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Storage\DataMysql;

abstract class IdxAbstract extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write
    private bool $isConfig                  = false;    // 是否已配置
    private string $tableName               = '';
    private string $fieldId                 = '';
    private string $fieldVal                = '';
    private string $fieldFrontNum           = '';
    private string $fieldBackNum            = '';

    /**
     * @return static
     * tag
     */
    public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param string $tableName
     * @param string $fieldId
     * @param string $fieldVal
     * @param string $fieldFrontNum
     * @param string $fieldBackNum
     * @return $this
     * config
     */
    protected function config(string $tableName, string $fieldId, string $fieldVal, string $fieldFrontNum, string $fieldBackNum):self
    {
        if($this->isConfig) return $this;
        $this->tableName        = $tableName;
        $this->fieldId          = $fieldId;
        $this->fieldVal         = $fieldVal;
        $this->fieldFrontNum    = $fieldFrontNum;
        $this->fieldBackNum     = $fieldBackNum;
        $this->isConfig         = true;
        return $this;
    }

    /**
     * @param string $val
     * @param string $frontNumStr
     * @param string $backNumStr
     * @return string
     * calcValMd5Num
     */
    private function calcValMd5Num(string $val, string &$frontNumStr, string &$backNumStr):string
    {
        $md5            = md5($val);
        $decNumList     = CommString::hexToDecArray(substr($md5, 0, 16).strrev(substr($md5, 16, 16)));
        $frontNumStr    = $decNumList[0]??'';
        $backNumStr     = $decNumList[1]??'';
        return $md5;
    }

    /**
     * @param string $val
     * @param string $frontNumStr
     * @param string $backNumStr
     * @return int
     * getCreateId
     */
    private function getCreateId(string $val, string $frontNumStr, string $backNumStr):int
    {
        if(strlen($frontNumStr) < 1 || strlen($backNumStr) < 1 || !CommValid::isNumber($frontNumStr) || !CommValid::isNumber($backNumStr)) return 0;
        $id             = $this->DbAuto->getDataId('INSERT INTO '.$this->DbAuto->getTableNameAll($this->tableName).' SET `'.$this->fieldFrontNum.'`='.$frontNumStr.', `'.$this->fieldBackNum.'`='.$backNumStr.', `'.$this->fieldVal.'`=\''.$this->DbAuto->getRealEscapeString($val).'\'');
        if($id > 0) return $id;
        return $this->getIdByNum($frontNumStr, $backNumStr);
    }

    /**
     * @param string $frontNumStr
     * @param string $backNumStr
     * @return int
     * getIdByNum
     */
    private function getIdByNum(string $frontNumStr, string $backNumStr):int
    {
        if(strlen($frontNumStr) < 1 || strlen($backNumStr) < 1 || !CommValid::isNumber($frontNumStr) || !CommValid::isNumber($backNumStr)) return 0;
        return $this->DbAuto->getDataInt('SELECT `'.$this->fieldId.'` AS _idx_id FROM '.$this->DbAuto->getTableNameAll($this->tableName).' WHERE `'.$this->fieldFrontNum.'`='.$frontNumStr.' AND `'.$this->fieldBackNum.'`='.$backNumStr, '_idx_id');
    }

    /**
     * @param int $id
     * @param bool $isExists
     * @return string
     * getValById
     */
    public function getValById(int $id, bool &$isExists = false):string
    {
        $isExists       = false;
        if($id < 1) return '';
        $isFail         = false;
        $valData        = $this->DbAuto->getDataOne('SELECT `'.$this->fieldVal.'` AS _idx_val FROM '.$this->DbAuto->getTableNameAll($this->tableName).' WHERE `'.$this->fieldId.'`='.$id, $isFail);
        if($isFail || !isset($valData['_idx_val'])) return '';
        $isExists       = true;
        return $valData['_idx_val'];
    }

    /**
     * @param string $val
     * @param string $frontNumStr
     * @param string $backNumStr
     * @return int
     * getIdByVal
     */
    public function getIdByVal(string $val, string &$frontNumStr = '', string &$backNumStr = ''):int
    {
        if(strlen($val) < 1) return 0;
        $frontNumStr    = '';
        $backNumStr     = '';
        $valMd5         = $this->calcValMd5Num($val, $frontNumStr, $backNumStr);
        unset($valMd5);
        return $this->getIdByNum($frontNumStr, $backNumStr);
    }

    /**
     * @param string $val
     * @param string $frontNumStr
     * @param string $backNumStr
     * @return int
     * getIdByValCreate
     */
    public function getIdByValCreate(string $val, string &$frontNumStr = '', string &$backNumStr = ''):int
    {
        if(strlen($val) < 1) return 0;
        $id             = $this->getIdByVal($val, $frontNumStr, $backNumStr);
        if($id > 0) return $id;
        return $this->getCreateId($val, $frontNumStr, $backNumStr);
    }
}